package seatiger.tomcat.catalina.connector;

import seatiger.tomcat.catalina.Context;
import seatiger.tomcat.catalina.Globals;
import seatiger.tomcat.catalina.Wrapper;
import seatiger.tomcat.coyote.Adapter;
import seatiger.tomcat.coyote.Request;
import seatiger.tomcat.util.buf.ByteChunk;
import seatiger.tomcat.util.http.MimeHeaders;
import seatiger.tomcat.util.http.mapper.Mapper;

import javax.servlet.http.Cookie;
import java.util.ArrayList;
import java.util.List;

/**
 * Adapter实现类，主要用于请求处理实现
 */
public class CoyoteAdapter implements Adapter {

    /**
     * uri 中重写的session_id
     */
    private static final String match =
            ";" + Globals.SESSION_PARAMETER_NAME + "=";

    public CoyoteConnector connector;

    public CoyoteAdapter(CoyoteConnector connector) {
        this.connector = connector;
    }

    @Override
    public void service(seatiger.tomcat.coyote.Request req,seatiger.tomcat.coyote.Response res) throws Exception {

        NewRequest request = connector.createNewRequest();
        request.setCoyoteRequest(req);

        NewResponse response = connector.createNewResponse();
        response.setCoyoteResponse(res);

        request.setResponse(response);

        if (postParseRequest(req,request)){
            //TODO业务处理逻辑
            connector.getContainer().getPipeline().getFirst().invoke(request,response);
        }
        response.finishResponse();
    }

    /**
     * 解析请求路径，并匹配Wrapper
     * @param req
     * @param request
     * @return
     */
    protected boolean postParseRequest(seatiger.tomcat.coyote.Request req, NewRequest request) {
        parseSessionId(req,request);
        MimeHeaders mimeHeaders = req.getMimeHeaders();
        String host = mimeHeaders.getHeader("host");
        String uri = req.requestURI().toString();
        Mapper mapper = connector.getMapper();
        Wrapper wrapper = (Wrapper) mapper.findWrapper(host.split(":")[0], uri);
        if (wrapper != null) {
            request.setWrapper(wrapper);
            request.setContext((Context) wrapper.getParent());
        }

        //解析cookie 中的session id
        parseSessionCookiesId(req, request);
        return true;
    }


    /**
     * 解析cookie 中的session id
     * @param req
     */
    protected void parseSessionCookiesId(Request req,NewRequest request) {
        if (request.getRequestedSessionId() == null && !request.isRequestedSessionURL()) {
            MimeHeaders mimeHeaders = req.getMimeHeaders();
            String cookieValue = mimeHeaders.getHeader("cookie");
            List<Cookie> cookies = parseCookieHeader(cookieValue);
            cookies.stream().filter(cookie -> Globals.SESSION_COOKIE_NAME.equals(cookie.getName()))
                    .forEach(cookie -> request.setRequestedSessionId(cookie.getValue()));
        }
    }


    /**
     * 如果用户URL重写功能 session 功能，需要将uri中的sessionid区出来
     * http://127.0.0.1:8081/myApp/test1;jsessionid=1234567890
     *
     * 解析session id,并将uri中;jsessionid=1234567890 去除
     * @param req
     * @param request
     */
    protected void parseSessionId(Request req,NewRequest request) {
        ByteChunk uriBC = req.requestURI().getByteChunk();
        int semicolon = uriBC.indexOf(match, 0, match.length(), 0);
        if (semicolon > 0) {
            int start = uriBC.getStart();
            int end = uriBC.getEnd();
            int sessionIdStart = semicolon + match.length();
            int semicolon2 = uriBC.indexOf(';', sessionIdStart);
            if (semicolon2 >= 0) {
                request.setRequestedSessionId
                        (new String(uriBC.getBuff(), start + sessionIdStart,
                                semicolon2 - sessionIdStart));
                // Extract session ID from request URI
                byte[] buf = uriBC.getBuff();
                for (int i = 0; i < end - start - semicolon2; i++) {
                    buf[start + semicolon + i]
                            = buf[start + i + semicolon2];
                }
                uriBC.setBytes(buf, start, end - start - semicolon2 + semicolon);
            } else {
                request.setRequestedSessionId
                        (new String(uriBC.getBuff(), start + sessionIdStart,
                                (end - start) - sessionIdStart));
                uriBC.setEnd(start + semicolon);
            }
            request.setRequestedSessionURL(true);
        } else {
            request.setRequestedSessionURL(false);
            request.setRequestedSessionId(null);
        }
    }


    private List<Cookie> parseCookieHeader(String headValue){
        if (headValue == null || headValue.length() == 0){
            return new ArrayList<>(0);
        }
        String[] heads = headValue.split(";");
        List<Cookie> cookies = new ArrayList<>(1);
        for (String head: heads){
            String[] split = head.split("=");
            cookies.add(new Cookie(split[0],split[1]));
        }
        return cookies;
    }
}
